v: ub\
'2021.0323                                    ',10,\
'www.flatassembler.net/download.php           ',10,\
'www.board.flatassembler.net/topic.php?t=12725',0








align 4
text: rb 1024*1024 && .szMax = $-text-1 ;0byte reserve
.szNow = 0

get_fasmdir: ub 'pose to fasm sources directory plz',0
if ~(SelectDirA get_fasmdir text) &&ret&& endif
cdA text text ;wanted final

call version.inc
call variable.inc
call preproce.inc

pause 'Done!'\
      'Recompile sources'
ret








preproce.inc: ub 'preproce.inc',0

;read the file and 0byte terminate it in buffer
text.szNow == ReadFileA text preproce.inc 0 text.szMax
if text.szNow = -1 && hlt 'preproce.inc read failure' && end if
ub[text+text.szNow]=0

;find preprocessor: label and do patch0
.find0: ub 'preprocessor:',0
.pos == posz 0 0 .find0 text 1 0
if .pos=0 && hlt 'preproce.inc analisys failure' && end if
nl.buffer==text && nl.szBuffer==(text.szNow+1) && nl.start==.pos && call nl
ui32[opm.argptr+4]=dataseg+.patch0 && call opm.ret
if (ShiftInBuffer text text.szNow text.szMax (nl.@stopper-1) opm.eax)<>'ok' && hlt 'reserve more space for text buffer' && end if
memcopy (text+nl.@stopper-1) opm.buffer opm.eax
text.szNow == text.szNow + opm.eax

;find include_file: label and do patch1
.find1: ub 'include_file:',0
.pos == posz strings.flagREVERSE 0 .find1 text 1 0
if .pos=0 && hlt 'preproce.inc analisys failure' && end if
nl.buffer==text && nl.szBuffer==(text.szNow+1) && nl.start==.pos && call nl
ui32[opm.argptr+4]=dataseg+.patch1 && call opm.ret
text.szNow == nl.@stopper-1 + opm.eax
if text.szNow>text.szMax && hlt 'reserve more space for text buffer' && end if
memcopy (text+nl.@stopper-1) opm.buffer (opm.eax+1)  ;+0byte

;write... aaaah
if (WriteFileA text preproce.inc 0 text.szNow)<>text.szNow && hlt 'preproce.inc write failure' && end if
ret

.patch0: ub\
\'preprocessor:                                                                                                ',10,\
';Tomasz, keep include_file: logics same and trailing the file plz!                                           ',10,\
'if INCLUDEONCE.DO and INCLUDEONCE.DO_ONCE <> 0                                                               ',10,\
'        mov     [includes.count],0      ;redundant, rather informal                                          ',10,\
'        mov     [includes.files],0      ;last include is none yet                                            ',10,\
'end if                                                                                                       ',0

.patch1: ub\
\'include_file:                                                                                                ',10,\
'        lods    byte [esi]                                                                                   ',10,\
'if INCLUDEONCE.DO and INCLUDEONCE.DO_ONCE <> 0                                                               ',10,\
'        mov     byte[includes.flags],al ;remember include form                                               ',10,\
'        cmp     al,1Ah                                                                                       ',10,\
'        jne     common_include          ;no once key                                                         ',10,\
'        lodsb                                                                                                ',10,\
'        cmp     al,4                                                                                         ',10,\
'        jne     invalid_argument        ;length("once")=4                                                    ',10,\
'        lodsd                                                                                                ',10,\
'        or      eax,"    "              ;case ignorant                                                       ',10,\
'        cmp     eax,"once"                                                                                   ',10,\
'        jne     invalid_argument        ;no once key                                                         ',10,\
'        lodsb                           ;resume common include                                               ',10,\
'      common_include:                                                                                        ',10,\
'end if                                                                                                       ',10,\
'        cmp     al,22h                                                                                       ',10,\
'        jne     invalid_argument                                                                             ',10,\
'        lods    dword [esi]                                                                                  ',10,\
'        cmp     byte [esi+eax],0                                                                             ',10,\
'        jne     extra_characters_on_line                                                                     ',10,\
'        push    esi                                                                                          ',10,\
'        push    edi                                                                                          ',10,\
'        mov     ebx,[current_line]                                                                           ',10,\
'      find_current_file_path:                                                                                ',10,\
'        mov     esi,[ebx]                                                                                    ',10,\
'        test    byte [ebx+7],80h                                                                             ',10,\
'        jz      copy_current_file_path                                                                       ',10,\
'        mov     ebx,[ebx+8]                                                                                  ',10,\
'        jmp     find_current_file_path                                                                       ',10,\
'      copy_current_file_path:                                                                                ',10,\
'        lods    byte [esi]                                                                                   ',10,\
'        stos    byte [edi]                                                                                   ',10,\
'        or      al,al                                                                                        ',10,\
'        jnz     copy_current_file_path                                                                       ',10,\
'      cut_current_file_name:                                                                                 ',10,\
'        cmp     edi,[esp]                                                                                    ',10,\
'        je      current_file_path_ok                                                                         ',10,\
'        cmp     byte [edi-1],"\"                                                                             ',10,\
'        je      current_file_path_ok                                                                         ',10,\
'        cmp     byte [edi-1],"/"                                                                             ',10,\
'        je      current_file_path_ok                                                                         ',10,\
'        dec     edi                                                                                          ',10,\
'        jmp     cut_current_file_name                                                                        ',10,\
'      current_file_path_ok:                                                                                  ',10,\
'        mov     esi,[esp+4]                                                                                  ',10,\
'        call    expand_path                                                                                  ',10,\
'        pop     edx                                                                                          ',10,\
'        mov     esi,edx                                                                                      ',10,\
'        call    open                                                                                         ',10,\
'        jnc     include_path_ok                                                                              ',10,\
'        mov     ebp,[include_paths]                                                                          ',10,\
'      try_include_directories:                                                                               ',10,\
'        mov     edi,esi                                                                                      ',10,\
'        mov     esi,ebp                                                                                      ',10,\
'        cmp     byte [esi],0                                                                                 ',10,\
'        je      try_in_current_directory                                                                     ',10,\
'        push    ebp                                                                                          ',10,\
'        push    edi                                                                                          ',10,\
'        call    get_include_directory                                                                        ',10,\
'        mov     [esp+4],esi                                                                                  ',10,\
'        mov     esi,[esp+8]                                                                                  ',10,\
'        call    expand_path                                                                                  ',10,\
'        pop     edx                                                                                          ',10,\
'        mov     esi,edx                                                                                      ',10,\
'        call    open                                                                                         ',10,\
'        pop     ebp                                                                                          ',10,\
'        jnc     include_path_ok                                                                              ',10,\
'        jmp     try_include_directories                                                                      ',10,\
'        mov     edi,esi                                                                                      ',10,\
'      try_in_current_directory:                                                                              ',10,\
'        mov     esi,[esp]                                                                                    ',10,\
'        push    edi                                                                                          ',10,\
'        call    expand_path                                                                                  ',10,\
'        pop     edx                                                                                          ',10,\
'        mov     esi,edx                                                                                      ',10,\
'        call    open                                                                                         ',10,\
'        jc      file_not_found                                                                               ',10,\
'      include_path_ok:                                                                                       ',10,\
'if INCLUDEONCE.DO and INCLUDEONCE.DO_WINAPI_FIX_FASM_BACKSEEK_BUG <> 0                                       ',10,\
'        sub     esp,8+260                                                                                    ',10,\
'        mov     eax,esp                                                                                      ',10,\
'        invoke  GetFullPathName,esi,260,eax,0                                                                ',10,\
'        lea     ecx,[eax+0] ;-->-----------\                                                                 ',10,\
'        mov     esi,esp     ;-->--\        ;                                                                 ',10,\
'        add     esp,8+260         ;        ;                                                                 ',10,\
'end if                            ;        ;                                                                 ',10,\
'        mov     edi,[esp]         ;        ;                                                                 ',10,\
'      copy_preprocessed_path:     ;        ;                                                                 ',10,\
'        lods    byte [esi]     ;<-/        ;                                                                 ',10,\
'if INCLUDEONCE.DO and INCLUDEONCE.DO_ONCE <> 0                                                               ',10,\
'        movzx   eax,al                     ;                                                                 ',10,\
'        mov     al,[upper_case_table+eax]  ;                                                                 ',10,\
'end if                                     ;                                                                 ',10,\
'        stos    byte [edi]                 ;                                                                 ',10,\
'        or      al,al                      ;                                                                 ',10,\
'        jnz     copy_preprocessed_path     ;                                                                 ',10,\
'        pop     esi                        ;                                                                 ',10,\
'if INCLUDEONCE.DO and INCLUDEONCE.DO_WINAPI_FIX_FASM_BACKSEEK_BUG = 0                                        ',10,\
'        lea     ecx,[edi-1]                ;                                                                 ',10,\
'        sub     ecx,esi                 ;<-/                                                                 ',10,\
'end if                                                                                                       ',10,\
'        mov     [esi-4],ecx                                                                                  ',10,\
'if INCLUDEONCE.DO and INCLUDEONCE.DO_ONCE <> 0                                                               ',10,\
'        mov     [esp-8],edi                                                                                  ',10,\
'        ;[esp-4]     =FullName                                                                               ',10,\
'        ;[esp-8]     =beyond FullName0                                                                       ',10,\
'        ;[FullName-4]=length(FullName)                                                                       ',10,\
'        cmp     byte[includes.flags],1Ah                                                                     ',10,\
'        jne     .include_file                                                                                ',10,\
'        mov     edx,includes.files-4                                                                         ',10,\
'      .match_next_include:                                                                                   ',10,\
'        add     edx,4                                                                                        ',10,\
'        mov     edi,[edx]                                                                                    ',10,\
'        test    edi,edi                                                                                      ',10,\
'        jz      .include_file                                                                                ',10,\
'        mov     esi,[esp-4]                                                                                  ',10,\
'        mov     ecx,[esi-4]                                                                                  ',10,\
'        cmp     ecx,[edi-4]                                                                                  ',10,\
'        jne     .match_next_include                                                                          ',10,\
'        repe    cmpsb                                                                                        ',10,\
'        jne     .match_next_include                                                                          ',10,\
'      .!include_file:                                                                                        ',10,\
'        call    close                                                                                        ',10,\
'        mov     edi,[current_line]                                                                           ',10,\
'        mov     byte[edi],0                                                                                  ',10,\
'        jmp     line_preprocessed                                                                            ',10,\
'      .include_file:                                                                                         ',10,\
'        mov     edi,[includes.count]                                                                         ',10,\
'        lea     edi,[includes.files+edi*4]                                                                   ',10,\
'        cmp     edi,includes.limit                                                                           ',10,\
'        je      out_of_memory                                                                                ',10,\
'        inc     [includes.count]                                                                             ',10,\
'        mov     esi,[esp-4]                                                                                  ',10,\
'        mov     [edi],esi                                                                                    ',10,\
'        mov     [edi+4],dword 0                                                                              ',10,\
'        mov     edi,[esp-8]                                                                                  ',10,\
'  if INCLUDEONCE.DO and INCLUDEONCE.DO_WINAPI_LIST_INCLUDES = INCLUDEONCE.DO_WINAPI_LIST_INCLUDES            ',10,\
'        jmp     .list_includes_after_any_include_4_debug_purpose                                             ',10,\
'      .includes_file : db "includes.txt",0                                                                   ',10,\
'      .includes_count: db "dword[includes.count] = %u",10,10,0                                               ',10,\
'    .list_includes_after_any_include_4_debug_purpose:                                                        ',10,\
'        pusha                                                                                                ',10,\
'        lea     ebp,[esp+7*4] ;@eax, no matter, winapi needs ioResult pointer                                ',10,\
'        invoke  CreateFile,.includes_file,GENERIC_WRITE,FILE_SHARE_READ,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0',10,\
'        mov     ebx,eax                                                                                      ',10,\
'                                                                                                             ',10,\
'        sub     esp,260                                                                                      ',10,\
'        mov     esi,esp                                                                                      ',10,\
'        cinvoke wsprintf,esi,.includes_count,[includes.count]                                                ',10,\
'        invoke  WriteFile,ebx,esi,eax,ebp,0                                                                  ',10,\
'        add     esp,260                                                                                      ',10,\
'                                                                                                             ',10,\
'        mov     edi,includes.files-4                                                                         ',10,\
'      .liaai4dp.loop:                                                                                        ',10,\
'        add     edi,4                                                                                        ',10,\
'        mov     esi,[edi]                                                                                    ',10,\
'        test    esi,esi                                                                                      ',10,\
'        jz      .liaai4dp.loop.                                                                              ',10,\
'        mov     ecx,[esi-4]                                                                                  ',10,\
'        mov     byte[esi+ecx],10                                                                             ',10,\
'        push    ecx                                                                                          ',10,\
'        inc     ecx                                                                                          ',10,\
'        invoke  WriteFile,ebx,esi,ecx,ebp,0                                                                  ',10,\
'        pop     ecx                                                                                          ',10,\
'        mov     byte[esi+ecx],0                                                                              ',10,\
'        jmp     .liaai4dp.loop                                                                               ',10,\
'      .liaai4dp.loop.:                                                                                       ',10,\
'                                                                                                             ',10,\
'        invoke  CloseHandle,ebx                                                                              ',10,\
'        popa                                                                                                 ',10,\
'  end if                                                                                                     ',10,\
'end if                                                                                                       ',10,\
'        push    dword [macro_status]                                                                         ',10,\
'        and     [macro_status],0Fh                                                                           ',10,\
'        call    preprocess_file                                                                              ',10,\
'        pop     eax                                                                                          ',10,\
'        and     al,0F0h                                                                                      ',10,\
'        and     [macro_status],0Fh                                                                           ',10,\
'        or      [macro_status],al                                                                            ',10,\
'        jmp     line_preprocessed                                                                            ',0








pose_next_line: && nl:
if .szBuffer=0 | .start=0 | .start>.szBuffer &&ret&& end if
  .@stopper == .start-1
while .@stopper < .szBuffer
  .stopper  == ub[.buffer+.@stopper]
  .@stopper == .@stopper+1
  if .stopper=0 | .stopper=10 | .stopper=13 &&ret&& end if
end while
ret
;caller inits vars
.buffer   = ;memory
.szBuffer = ;its size including 0byte
.start    = ;1+
;caller receives
.@stopper = ;1+
.stopper  = ;0byte|LF|CR








variable.inc: ub 'variable.inc',0
text.szNow == ReadFileA text variable.inc 0 text.szMax
if text.szNow = -1
   hlt 'variable.inc read failure'
end if
ub[text+text.szNow]=0
.patch0: ub\
'if INCLUDEONCE.DO and INCLUDEONCE.DO_ONCE <> 0                                                               ',10,\
'align 4                                                                                                      ',10,\
'includes:                                                                                                    ',10,\
'  .flags rd 1                                                                                                ',10,\
'  .count rd 1                                                                                                ',10,\
'  .files rd $ffff                                                                                            ',10,\
'  .limit rd 1                                                                                                ',10,\
'end if                                                                                                       ',0
ui32[opm.argptr+4]=dataseg+.patch0 && call opm.ret
if (ShiftInBuffer text text.szNow text.szMax text.szNow opm.eax)<>'ok'
   hlt 'reserve more space for text buffer'
end if
memcopy (text+text.szNow) opm.buffer opm.eax
text.szNow == text.szNow + opm.eax
if (WriteFileA text variable.inc 0 text.szNow) = -1
   hlt 'variable.inc write failure'
end if
ret








version.inc: ub 'version.inc',0
text.szNow == ReadFileA text version.inc 0 text.szMax
if text.szNow = -1
   hlt 'version.inc read failure'
end if
ub[text+text.szNow]=0
if (posz 0 0 opm text 1 0)<>0
   hlt 'seems already patched'
end if
.patch0: ub\
'virtual at 0                                                                                                 ',10,\
'INCLUDEONCE:                                                                                                 ',10,\
'  .DO_ONCE                         = 001b                                                                    ',10,\
'  .DO_WINAPI_FIX_FASM_BACKSEEK_BUG = 010b                                                                    ',10,\
'  .DO_WINAPI_LIST_INCLUDES         = 100b or .DO_ONCE                                                        ',10,\
'  .DO                              = .DO_ONCE or .DO_WINAPI_FIX_FASM_BACKSEEK_BUG or .DO_WINAPI_LIST_INCLUDES',10,\
'display 13,10,"INCLUDEONCE.DO=",.DO+"0"                                                                      ',10,\
'end virtual                                                                                                  ',0
ui32[opm.argptr+4]=dataseg+.patch0 && call opm.ret
if (ShiftInBuffer text text.szNow text.szMax text.szNow opm.eax)<>'ok'
   hlt 'reserve more space for text buffer'
end if
memcopy (text+text.szNow) opm.buffer opm.eax
text.szNow == text.szNow + opm.eax
if (WriteFileA text version.inc 0 text.szNow) = -1
   hlt 'version.inc write failure'
end if
ret








once_patch_marker: && opm: ub ';;include once (fasm patch autogen)',0
.format: ub 10,'%s',10,'%s',10,'%s',0
align 4
.buffer: rb 1'0000h && .szBuffer = $-.buffer
.argptr: ui32 dataseg+opm,,dataseg+opm
.ret: .eax == printfA .buffer .szBuffer .format .argptr
ret
